package com.sun.async.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.async.entity.Student;
import com.sun.async.entity.dto.StudentImportDTO;
import com.sun.async.mapper.StudentMapper;
import com.sun.async.service.AsyncExcelImportService;
import com.sun.async.service.FileStorageService;
import com.sun.async.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 学生服务实现类
 */
@Slf4j
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

    @Autowired
    private FileStorageService fileStorageService;

    @Override
    public ImportProcessResult processImportData(List<StudentImportDTO> studentImportDTOList) {
        if (CollectionUtils.isEmpty(studentImportDTOList)) {
            return new ImportProcessResult(0, new ArrayList<>());
        }

        List<StudentImportDTO> failedRecords = new ArrayList<>();
        int successCount = 0;

        for (StudentImportDTO dto : studentImportDTOList) {
            // 校验DTO
            String validationError = validateRow(dto);
            if (validationError != null) {
                dto.setErrorMsg(validationError);
                failedRecords.add(dto);
                continue;
            }

            // 转换DTO为实体
            Student student = convertToEntity(dto);

            try {
                // 保存到数据库
                this.save(student);
                successCount++;
            } catch (Exception e) {
                // 保存失败
                dto.setErrorMsg("保存数据库失败: " + e.getMessage());
                failedRecords.add(dto);
            }
        }

        return new ImportProcessResult(successCount, failedRecords);
    }

    @Override
    public Class<StudentImportDTO> getDtoClass() {
        return StudentImportDTO.class;
    }

    @Override
    public AsyncExcelImportService.ImportResult processData(List<StudentImportDTO> dataList) {
        ImportProcessResult result = processImportData(dataList);

        // 生成错误文件
        String errorFilePath = null;
        if (!result.getFailedRecords().isEmpty()) {
            errorFilePath = generateErrorFile("students.xlsx", result.getFailedRecords());
        }

        return new AsyncExcelImportService.ImportResult(
                result.getSuccessCount(),
                result.getFailedRecords(),
                errorFilePath
        );
    }

    @Override
    public String validateRow(StudentImportDTO dto) {
        List<String> errors = new ArrayList<>();

        if (dto.getName() == null || dto.getName().trim().isEmpty()) {
            errors.add("姓名不能为空");
        }

        if (dto.getAge() == null) {
            errors.add("年龄不能为空");
        } else if (dto.getAge() < 1) {
            errors.add("年龄不能小于1");
        } else if (dto.getAge() > 100) {
            errors.add("年龄不能大于100");
        }

        if (dto.getGender() == null) {
            errors.add("性别不能为空");
        }

        if (!errors.isEmpty()) {
            return String.join("; ", errors);
        }

        return null;
    }

    /**
     * 将DTO转换为实体
     * @param dto 学生DTO
     * @return 学生实体
     */
    private Student convertToEntity(StudentImportDTO dto) {
        Student student = new Student();
        student.setName(dto.getName());
        student.setAge(dto.getAge());
        student.setGender(dto.getGender());
        student.setPhone(dto.getPhone());
        return student;
    }

    /**
     * 生成错误文件
     */
    private String generateErrorFile(String originalFileName, List<StudentImportDTO> failedRecords) {
        if (CollectionUtils.isEmpty(failedRecords)) {
            return null;
        }
        try {
            // 创建临时文件
            String fileName = System.currentTimeMillis() + "_error_" + originalFileName;
            File errorFile = new File(fileStorageService.getUploadPath(), fileName);

            // 设置表头样式
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            headWriteCellStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());
            WriteFont headWriteFont = new WriteFont();
            headWriteFont.setFontHeightInPoints((short)12);
            headWriteFont.setBold(true);
            headWriteCellStyle.setWriteFont(headWriteFont);

            // 设置内容样式
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
            contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
            contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
            contentWriteCellStyle.setBorderTop(BorderStyle.THIN);

            // 水平样式策略
            HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                    new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

            // 获取DTO类
            Class<?> dtoClass = failedRecords.get(0).getClass();

            // 写入错误文件
            EasyExcel.write(errorFile, dtoClass)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .sheet("错误数据")
                    .doWrite(failedRecords);

            return fileStorageService.getRelativePath(fileName);
        } catch (Exception e) {
            log.error("生成错误文件失败", e);
            return null;
        }
    }
}